package com.ym.utils.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @version v1.0
 * @ProjectName: SpringCloud-Alibaba-YM
 * @ClassName: GeoUtil
 * @Description: 地理位置
 * @Author: 晨曦
 * @Date: 2021-8-27 13:54
 * GEOADD
 *  时间复杂度为O(log(N)),添加经纬度信息
 * GEOPOS
 *  时间复杂度为O(log(N)),查找指定key的经纬度信息，可以指定多个key，批量返回
 * GEODIST
 *  时间复杂度为O(log(N)),返回两个地方的距离，可以指定单位，比如米m，千米km，英里mi，英尺ft
 * GEORADIUS
 *  时间复杂度为O(N+log(M))，N为指定半径范围内的元素个数，M为要返回的个数
 *  根据给定的经纬度，返回半径不超过指定距离的元素
 *  可以指定WITHDIST返回距离，WITHCOORD返回经纬度，WITHHASH返回geohash值
 *  可以指定ASC或DESC，根据距离来排序
 *  可以指定COUNT限定返回的记录数
 * GEORADIUSBYMEMBER
 *  时间复杂度为O(log(N)+M)，N为指定半径范围内的元素个数，M为要返回的个数
 *  根据指定的地点查询半径在指定范围内的位置
 *  可以指定WITHDIST返回距离，WITHCOORD返回经纬度，WITHHASH返回geohash值
 *  可以指定ASC或DESC，根据距离来排序
 *  可以指定COUNT限定返回的记录数
 * GEOHASH
 *  查找一个位置的时间复杂度为O(log(N))
 *  返回的是geohash值
 *
 *  地址： http://redisdoc.com/geo/geoadd.html
 */
@Slf4j
@Component
public class GeoUtil {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;


    public void geoAdd(String cityGeoKey, Point point,String member){
        Long addedNum = redisTemplate.opsForGeo().add(cityGeoKey,point,member);
        System.out.println(addedNum);
    }

    public void geoGet(String cityGeoKey,String members){
        List<Point> points = redisTemplate.opsForGeo().position(cityGeoKey,members);
        System.out.println(points);
    }

    public void geoDist(String cityGeoKey, String memberFrom, String memberTo, Metric metric ){
        Distance distance = redisTemplate.opsForGeo().distance(cityGeoKey,memberFrom,memberTo, metric);
        System.out.println(distance);
    }

    public void nearByXY(String cityGeoKey,double centerX, double centerY){
        //longitude,latitude
        Circle circle = new Circle(centerX,centerY, Metrics.KILOMETERS.getMultiplier());
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance().includeCoordinates().sortAscending().limit(5);
        GeoResults<RedisGeoCommands.GeoLocation<Object>>  results = redisTemplate.opsForGeo().radius(cityGeoKey,circle,args);
        System.out.println(results);
    }

    public void nearByPlace(String cityGeoKey,String member,double value){
        Distance distance = new Distance(value,Metrics.KILOMETERS);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance().includeCoordinates().sortAscending().limit(5);
        GeoResults<RedisGeoCommands.GeoLocation<Object>>  results = redisTemplate.opsForGeo()
                .radius(cityGeoKey,member,distance,args);
        System.out.println(results);
    }

    public void geoHash(String cityGeoKey,String members){
        List<String> results = redisTemplate.opsForGeo()
                .hash(cityGeoKey,members);
        System.out.println(results);
    }




}
